package club.jdiy.core.base;

import club.jdiy.core.base.domain.DBEntity;
import club.jdiy.core.base.domain.Filterable;
import club.jdiy.core.base.domain.Pager;
import club.jdiy.core.base.domain.Removable;
import club.jdiy.core.JDiyContext;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Optional;

/**
 * Service层的抽象基类实现
 *
 * @param <T>    实体类
 * @param <TDao> 实体的DAO类
 * @param <ID>   实体类的主键类型
 *
 * @author ziquee(子秋) QQ号:39886616 主页: http://www.jdiy.club
 * @version 20200519
 */
public abstract class JDiyBaseService<T extends DBEntity<ID>, TDao extends JDiyDao<T, ID>, ID>
        implements JDiyService<T, TDao, ID> {
    protected TDao dao;

    @Override
    @Transactional
    public void delete(T t) {
        this.findById(t.getId()).ifPresent(p -> {
            if (p instanceof Removable) {
                ((Removable) p).setRemoved(true);
                dao.save(p);
            } else {
                dao.delete(p);
            }
        });
    }

    @Override
    @Transactional
    public void deleteById(ID id) {
        findById(id).ifPresent(this::delete);
    }

    @Override
    @Transactional
    public <S extends T> S save(S s) {
        return dao.save(s);
    }

    @Override
    @Transactional
    public void insert(T t) {
        dao.insert(t);
    }

    @Override
    @Transactional
    public void insertAll(Iterable<T> entities) {
        dao.insertAll(entities);
    }

    @Override
    public Optional<T> findById(ID id) {
        return dao.findById(id);
    }

    @Override
    public List<T> findAllById(Iterable<ID> pks) {
        return dao.findAllById(pks);
    }

    @Override
    public <S extends T> Iterable<S> saveAll(Iterable<S> entities) {
        Assert.notNull(entities, "Entities must not be null!");
        return dao.saveAll(entities);
    }

    @Override
    @Transactional
    public void deleteAll(Iterable<? extends T> entities) {
        Assert.notNull(entities, "Entities must not be null!");
        entities.forEach(this::delete);
    }

    @Override
    public long count() {
        return dao.count();
    }

    @Override
    public boolean existsById(ID id) {
        return dao.existsById(id);
    }

    @Override
    public T getOne(ID id) {
        return dao.getOne(id);
    }

    @Override
    public long count(T t) {
        return dao.count(t);
    }
    @Override
    public long count(Filterable t) {
        return dao.count(t);
    }

    @Override
    public Pager<T> findPager(int pageSize, int page, T t, String order, String sort) {
        return this.dao.findPager(pageSize, page, t, order, sort);
    }
    @Override
    public Pager<T> findPager(int pageSize, int page, Filterable t, String order, String sort) {
        return this.dao.findPager(pageSize, page, t, order, sort);
    }

    @Override
    public List<T> findList(int count, T t, String order, String sort) {
        return dao.findList(count, t, order, sort);
    }

    @Override
    public List<T> findList(int count, Filterable t, String order, String sort) {
        return dao.findList(count, t, order, sort);
    }

    @Override
    public List<T> findAll() {
        return this.dao.findAll();
    }


    @PostConstruct
    @SuppressWarnings("ALL")
    private void init() {
        Class s = (Class<JDiyDao>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
        this.dao = (TDao) context.getApplicationContext().getBean(s);
    }

    @Resource
    protected JDiyContext context;
}
